#include "InjectDLL.h"

InjectDLL::InjectDLL(QObject *parent)
    : QObject(parent), QRunnable(), cond(new QWaitCondition), mutex(new QMutex)
{
}

void InjectDLL::Inject_init(DWORD pid, const QString &dllPath)
{
    this->pid = pid;
    this->dllPath = dllPath;
}

void InjectDLL::run()
{
    mutex->lock();
    if (!QFile::exists(dllPath))
    {
        emit SendDra(QString("DLL 文件不存在: %1").arg(dllPath));
        cond->wait(mutex);
        mutex->unlock();
        return;
    }

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!hProcess)
    {
        emit SendDra(QString("无法打开目标进程 ID: %1").arg(pid));
        cond->wait(mutex);
        mutex->unlock();
        return;
    }

    // QByteArray pathData = dllPath.toUtf8();
    long dll_size = dllPath.toStdWString().length() * sizeof(wchar_t) + 1;
    LPVOID remoteMemory = VirtualAllocEx(hProcess, nullptr, dll_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    if (!remoteMemory)
    {
        emit SendDra("无法在目标进程中分配内存");
        CloseHandle(hProcess);
        cond->wait(mutex);
        mutex->unlock();
        return;
    }

    if (!WriteProcessMemory(hProcess, remoteMemory,  dllPath.toStdWString().c_str(), dll_size, nullptr))
    {
        emit SendDra("无法写入目标进程内存");
        VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        cond->wait(mutex);
        mutex->unlock();
        return;
    }

    HMODULE hKernel32 = LoadLibrary(TEXT("kernel32.dll"));
    FARPROC loadLibraryAddr = GetProcAddress(hKernel32, "LoadLibraryW");

    if (!loadLibraryAddr)
    {
        emit SendDra("无法获取 LoadLibraryW 的地址");
        VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        cond->wait(mutex);
        mutex->unlock();
        return;
    }

    HANDLE hThread = CreateRemoteThread(hProcess, nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(loadLibraryAddr), remoteMemory, 0, nullptr);
    if (hThread == nullptr)
    {
        emit SendDra("创建远程线程失败");
        VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        cond->wait(mutex);
        mutex->unlock();
        return;
    }

    WaitForSingleObject(hThread, INFINITE);
    emit SendDra("成功注入 DLL: " + dllPath);
    // 清理资源
    CloseHandle(hThread);
    VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE);
    CloseHandle(hProcess);
    cond->wait(mutex);
    mutex->unlock();
}
